home *** CD-ROM | disk | FTP | other *** search
/ 17 Bit Software 6: Level 6 / 17 Bit - Level 6 (1998)(Epic Marketing)[!].iso / quartz / q0429.dms / q0429.adf / libray / libobj / bounds.c < prev    next >
C/C++ Source or Header  |  1992-05-20  |  6KB  |  246 lines

  1. /*
  2.  * bounds.c
  3.  *
  4.  * Copyright (C) 1989, 1991, Craig E. Kolb
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  * $Id: bounds.c,v 4.0.1.2 91/10/05 18:17:29 cek Exp Locker: cek $
  17.  *
  18.  * $Log:    bounds.c,v $
  19.  * Revision 4.0.1.2  91/10/05  18:17:29  cek
  20.  * patch1: Faster box transform, a la Jim Arvo.
  21.  * 
  22.  * Revision 4.0.1.1  1991/09/29  15:42:05  cek
  23.  * patch1: Justified floating point compare...
  24.  *
  25.  * Revision 4.0  91/07/17  14:36:21  kolb
  26.  * Initial version.
  27.  * 
  28.  */
  29. #include "geom.h"
  30.  
  31. /*
  32.  * Check for intersection between bounding box and the given ray.
  33.  * If there is an intersection between mindist and *maxdist along
  34.  * the ray, *maxdist is replaced with the distance to the point of
  35.  * intersection, and TRUE is returned.  Otherwise, FALSE is returned.
  36.  *
  37.  * If this routine is used to check for intersection with a volume
  38.  * rather than a "hollow" box, one should first determine if
  39.  * (ray->pos + mindist * ray->dir) is inside the bounding volume, and
  40.  * call BoundsIntersect() only if it is not.
  41.  */
  42. int
  43. BoundsIntersect(ray, bounds, mindist, maxdist)
  44. Ray *ray;
  45. Float bounds[2][3], mindist, *maxdist;
  46. {
  47.     Float t, tmin, tmax;
  48.     Float dir, pos;
  49.  
  50.     tmax = *maxdist;
  51.     tmin = mindist;
  52.  
  53.     dir = ray->dir.x;
  54.     pos = ray->pos.x;
  55.  
  56.     if (dir < 0) {
  57.         t = (bounds[LOW][X] - pos) / dir;
  58.         if (t < tmin)
  59.             return FALSE;
  60.         if (t <= tmax)
  61.             tmax = t;
  62.         t = (bounds[HIGH][X] - pos) / dir;
  63.         if (t >= tmin) {
  64.             if (t > tmax)
  65.                 return FALSE;
  66.             tmin = t;
  67.         }
  68.     } else if (dir > 0.) {
  69.         t = (bounds[HIGH][X] - pos) / dir;
  70.         if (t < tmin)
  71.             return FALSE;
  72.         if (t <= tmax)
  73.             tmax = t;
  74.         t = (bounds[LOW][X] - pos) / dir;
  75.         if (t >= tmin) {
  76.             if (t > tmax)
  77.                 return FALSE;
  78.             tmin = t;
  79.         }
  80.     } else if (pos < bounds[LOW][X] || pos > bounds[HIGH][X])
  81.         return FALSE;
  82.  
  83.     dir = ray->dir.y;
  84.     pos = ray->pos.y;
  85.  
  86.     if (dir < 0) {
  87.         t = (bounds[LOW][Y] - pos) / dir;
  88.         if (t < tmin)
  89.             return FALSE;
  90.         if (t <= tmax)
  91.             tmax = t;
  92.         t = (bounds[HIGH][Y] - pos) / dir;
  93.         if (t >= tmin) {
  94.             if (t > tmax)
  95.                 return FALSE;
  96.             tmin = t;
  97.         }
  98.     } else if (dir > 0.) {
  99.         t = (bounds[HIGH][Y] - pos) / dir;
  100.         if (t < tmin)
  101.             return FALSE;
  102.         if (t <= tmax)
  103.             tmax = t;
  104.         t = (bounds[LOW][Y] - pos) / dir;
  105.         if (t >= tmin) {
  106.             if (t > tmax)
  107.                 return FALSE;
  108.             tmin = t;
  109.         }
  110.     } else if (pos < bounds[LOW][Y] || pos > bounds[HIGH][Y])
  111.         return FALSE;
  112.  
  113.     dir = ray->dir.z;
  114.     pos = ray->pos.z;
  115.  
  116.     if (dir < 0) {
  117.         t = (bounds[LOW][Z] - pos) / dir;
  118.         if (t < tmin)
  119.             return FALSE;
  120.         if (t <= tmax)
  121.             tmax = t;
  122.         t = (bounds[HIGH][Z] - pos) / dir;
  123.         if (t >= tmin) {
  124.             if (t > tmax)
  125.                 return FALSE;
  126.             tmin = t;
  127.         }
  128.     } else if (dir > 0.) {
  129.         t = (bounds[HIGH][Z] - pos) / dir;
  130.         if (t < tmin)
  131.             return FALSE;
  132.         if (t <= tmax)
  133.             tmax = t;
  134.         t = (bounds[LOW][Z] - pos) / dir;
  135.         if (t >= tmin) {
  136.             if (t > tmax)
  137.                 return FALSE;
  138.             tmin = t;
  139.         }
  140.     } else if (pos < bounds[LOW][Z] || pos > bounds[HIGH][Z])
  141.         return FALSE;
  142.  
  143.     /*
  144.      * If tmin == mindist, then there was no "near"
  145.      * intersection farther than EPSILON away.
  146.      */
  147.     if (tmin == mindist) {
  148.         if (tmax < *maxdist) {
  149.             *maxdist = tmax;
  150.             return TRUE;
  151.         }
  152.     } else {
  153.         if (tmin < *maxdist) {
  154.             *maxdist = tmin;
  155.             return TRUE;
  156.         }
  157.     }
  158.     return FALSE;    /* hit, but not closer than maxdist */
  159. }
  160.  
  161. /*
  162.  * Transform an object's bounding box by the given transformation
  163.  * matrix.
  164.  */
  165. void
  166. BoundsTransform(trans, objbounds)
  167. RSMatrix *trans;
  168. Float objbounds[2][3];
  169. {
  170.     Float bounds[2][3], a, b;
  171.     int i, j;
  172.  
  173.     /*
  174.      * Can't (and shouldn't) do anything with unbounded objects.
  175.      */
  176.     if (objbounds[LOW][X] > objbounds[HIGH][X])
  177.         return;
  178.  
  179.     bounds[LOW][X] = bounds[HIGH][X] = trans->translate.x;
  180.     bounds[LOW][Y] = bounds[HIGH][Y] = trans->translate.y;
  181.     bounds[LOW][Z] = bounds[HIGH][Z] = trans->translate.z;
  182.  
  183.     for (i = 0; i < 3; i++) {
  184.         for (j = 0; j < 3; j++) {
  185.             a = trans->matrix[j][i] * objbounds[LOW][j];
  186.             b = trans->matrix[j][i] * objbounds[HIGH][j];
  187.             if (a < b) {
  188.                 bounds[LOW][i] += a;
  189.                 bounds[HIGH][i] += b;
  190.             } else {
  191.                 bounds[LOW][i] += b;
  192.                 bounds[HIGH][i] += a;
  193.             }
  194.         }
  195.     }
  196.     BoundsCopy(bounds, objbounds);
  197. }
  198.  
  199. void
  200. BoundsInit(bounds)
  201. Float bounds[2][3];
  202. {
  203.     bounds[LOW][X] = bounds[LOW][Y] = bounds[LOW][Z] = FAR_AWAY;
  204.     bounds[HIGH][X] = bounds[HIGH][Y] = bounds[HIGH][Z] = -FAR_AWAY;
  205. }
  206.  
  207. void
  208. BoundsCopy(from, into)
  209. Float into[2][3], from[2][3];
  210. {
  211.     into[LOW][X] = from[LOW][X];
  212.     into[LOW][Y] = from[LOW][Y];
  213.     into[LOW][Z] = from[LOW][Z];
  214.     into[HIGH][X] = from[HIGH][X];
  215.     into[HIGH][Y] = from[HIGH][Y];
  216.     into[HIGH][Z] = from[HIGH][Z];
  217. }
  218.  
  219. #define SetIfLess(a, b)        (a = ((a) < (b) ? (a) : (b)))
  220. #define SetIfGreater(a, b)    (a = ((a) > (b) ? (a) : (b)))
  221.  
  222. /*
  223.  * Find bounding box of the union of two bounding boxes.
  224.  */
  225. void
  226. BoundsEnlarge(old, new)
  227. Float old[2][3], new[2][3];
  228. {
  229.     SetIfLess(old[LOW][X], new[LOW][X]);
  230.     SetIfLess(old[LOW][Y], new[LOW][Y]);
  231.     SetIfLess(old[LOW][Z], new[LOW][Z]);
  232.     SetIfGreater(old[HIGH][X], new[HIGH][X]);
  233.     SetIfGreater(old[HIGH][Y], new[HIGH][Y]);
  234.     SetIfGreater(old[HIGH][Z], new[HIGH][Z]);
  235. }
  236.  
  237. void
  238. BoundsPrint(box, fp)
  239. Float box[2][3];
  240. FILE *fp;
  241. {
  242.     fprintf(fp,"\tX: %f to %f\n",box[LOW][X], box[HIGH][X]);
  243.     fprintf(fp,"\tY: %f to %f\n",box[LOW][Y], box[HIGH][Y]);
  244.     fprintf(fp,"\tZ: %f to %f\n",box[LOW][Z], box[HIGH][Z]);
  245. }
  246.